﻿using Microsoft.EntityFrameworkCore;
using star_questionnair.Models;
using star_questionnair.Utilities;

namespace star_questionnair.Services.impl;

/// <summary>
/// 历史记录服务实现，负责处理用户与问卷历史相关的业务逻辑
/// </summary>
public class HistoryService : IHistoryService
{
    private readonly ApplicationDbContext _dbContext;

    public HistoryService(ApplicationDbContext dbContext)
    {
        _dbContext = dbContext;
    }
    
    public async Task<Questionnaire> GetQuestionnaireByIdAsync(int questionnaireId)
    {
        // 获取问卷对象及其问题和选项
        var questionnaire = await _dbContext.Questionnaires
            .Include(q => q.Questions) // 预加载问题
            .ThenInclude(question => question.Options) // 预加载每个问题的选项
            .FirstOrDefaultAsync(q => q.Id == questionnaireId); // 使用异步的 FirstOrDefaultAsync

        if (questionnaire == null)
        {
            throw new Exception("查找问卷失败，无问卷");
        }

        // 设置问卷的响应数量
        questionnaire.Count = GetCountResponseInQuestionnaire(questionnaireId);

        return questionnaire;
    }

    public List<int> GetQuestionnaireIdsByUserId(int userId)
    {
        return _dbContext.Responses
            .Where(r => r.UserId == userId)
            .OrderByDescending(r => r.SubmittedTime)
            .Select(r => r.QuestionnaireId)
            .ToList();
    }

    public List<Questionnaire> GetQuestionnaireBySelf(int authorId)
    {
        // 根据 authorId 获取所有问卷
        return _dbContext.Questionnaires
            .Where(q => q.AuthorId == authorId)
            .ToList();
    }

    public List<Questionnaire> GetListQuestionnaireByUserId(int userId)
    {
        // 获取用户的所有 Response
        var responseList = _dbContext.Responses
            .Where(r => r.UserId == userId)
            .ToList();

        // 获取与 Response 关联的问卷列表
        var questionnaireIds = responseList.Select(r => r.QuestionnaireId).Distinct().ToList();
        var questionnaires = _dbContext.Questionnaires
            .Where(q => questionnaireIds.Contains(q.Id))
            .ToList();

        return questionnaires;
    }

    public List<Response> GetResponsesByUserId(int userId)
    {
        var responses = _dbContext.Responses
            .Where(r => r.UserId == userId)
            .OrderByDescending(r => r.SubmittedTime)
            .ToList();

        foreach (var response in responses)
        {
            response.Answers = GetAnswersByResponseId(response.Id);
        }

        return responses;
    }

    public void InsertHistoryAssociation(int userId, int questionnaireId)
    {
        var response = new Response
        {
            UserId = userId,
            QuestionnaireId = questionnaireId,
            SubmittedTime = DateTime.Now
        };

        _dbContext.Responses.Add(response);
        _dbContext.SaveChanges();
    }

    public List<Questionnaire> GetQuestionnairesByUserId(int userId)
    {
        var responseIds = GetQuestionnaireIdsByUserId(userId);
        return _dbContext.Questionnaires
            .Where(q => responseIds.Contains(q.Id))
            .ToList();
    }

    public List<Question> GetQuestionsByQuestionnaireId(int questionnaireId)
    {
        return _dbContext.Questions
            .Where(q => q.QuestionnaireId == questionnaireId)
            .OrderBy(q => q.Ordination)
            .ToList();
    }

    public List<Option> GetOptionsByQuestionId(int questionId)
    {
        return _dbContext.Options
            .Where(o => o.QuestionId == questionId)
            .OrderBy(o => o.Ordination)
            .ToList();
    }

    public List<Answer> GetAnswersByQuestionId(int questionId)
    {
        return _dbContext.Answers
            .Where(a => a.QuestionId == questionId)
            .ToList();
    }

    public List<Answer> GetAnswersByResponseId(int responseId)
    {
        return _dbContext.Answers
            .Where(a => a.ResponseId == responseId)
            .ToList();
    }

    public List<Answer> GetAnswersByUserAndQuestion(int userId, int questionId)
    {
        var response = _dbContext.Responses
            .FirstOrDefault(r =>
                r.UserId == userId && r.QuestionnaireId == GetQuestionByOptionId(questionId).QuestionnaireId);

        if (response == null)
            return new List<Answer>();

        return GetAnswersByResponseId(response.Id);
    }

    public Question GetQuestionByOptionId(int optionId)
    {
        var option = _dbContext.Options.Find(optionId);
        if (option == null)
            throw new ArgumentException("无效的选项ID，找不到对应的问题。");

        return _dbContext.Questions.Find(option.QuestionId);
    }

    public Answer GetAnswerByOptionId(int optionId)
    {
        var option = _dbContext.Options.Find(optionId);
        if (option == null)
            throw new ArgumentException("无效的选项ID，找不到对应的回答。");

        var answers = GetAnswersByQuestionId(option.QuestionId);
        return answers.FirstOrDefault(a => a.Content == optionId.ToString());
    }

    public Questionnaire GetCompleteQuestionnaire(int questionnaireId)
    {
        var questionnaire = _dbContext.Questionnaires.Find(questionnaireId);
        if (questionnaire == null)
            throw new Exception("找不到对应的问卷。");

        var questions = GetQuestionsByQuestionnaireId(questionnaireId);
        foreach (var question in questions)
        {
            question.Options = GetOptionsByQuestionId(question.Id);
        }

        questionnaire.Questions = questions;
        return questionnaire;
    }

    public List<Question> GetListQuestionByQuestionnaireId(int questionnaireId)
    {
        return _dbContext.Questions
            .Where(q => q.QuestionnaireId == questionnaireId)
            .OrderBy(q => q.Ordination) // 按照 ordination 字段升序排列
            .ToList();
    }

    public Questionnaire GetWholeQuestionnaire(int questionnaireId)
    {
        // 获取问卷对象
        var questionnaire = _dbContext.Questionnaires
            .Include(q => q.Questions) // 预加载问题
            .FirstOrDefault(q => q.Id == questionnaireId);

        if (questionnaire == null)
        {
            throw new Exception("查找问卷失败，无问卷");
        }

        // 设置问卷的响应数量
        questionnaire.Count = GetCountResponseInQuestionnaire(questionnaireId);

        // 为每个问题添加选项
        foreach (var question in questionnaire.Questions)
        {
            question.Options = GetListOptionByQuestionId(question.Id);
        }

        return questionnaire;
    }

    public async Task<List<Response>> GetListResponseByUserId(int userId)
    {
        // 查询所有符合条件的 Response
        var responseList = await _dbContext.Responses
            .Where(r => r.UserId == userId)
            .OrderByDescending(r => r.SubmittedTime)
            .ToListAsync();

        var responses = new List<Response>();
    
        foreach (var response in responseList)
        {
            // 获取该 Response 对应的所有 Answer
            var answerList = await GetListAnswerByResponseId(response.Id);
            response.Answers = answerList;  // 假设 Response 类有一个 Answers 属性
            responses.Add(response);
        }

        return responses;
    }
    
    public async Task<List<Answer>> GetListAnswerByResponseId(int responseId)
    {
        return await _dbContext.Answers
            .Where(a => a.ResponseId == responseId)
            .ToListAsync();
    }
    public long GetCountResponseInQuestionnaire(int questionnaireId)
    {
        return _dbContext.Responses.Count(r => r.QuestionnaireId == questionnaireId);
    }

    public List<Option> GetListOptionByQuestionId(int questionId)
    {
        return _dbContext.Options
            .Where(o => o.QuestionId == questionId)
            .OrderBy(o => o.Ordination) // 假设 Ordination 是排序字段
            .ToList();
    }
    
    public List<Response> GetListResponsesByQuestionnaireId(int questionnaireId)
    {
        return _dbContext.Responses
            .Where(r => r.QuestionnaireId == questionnaireId)
            .ToList();
    }

}